ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
MMA68xx.c
Go to the documentation of this file.
00001 
00017 #include "derivative.h"
00018 #include "utils.h" /* For Parity */
00019 #include "MMA68xx.h"
00020 #include "DSPI.h"
00021 #include "MailScheduler.h"
00022 #include <limits.h> /* To set limits */
00023 #include <stdlib.h>
00024 /*
00025  ******************************************************************************
00026  * constants
00027  ******************************************************************************
00028  */
00029 const uint16_t cau16MMA6800Reset[] =
00030 {
00031   /* Sequence below is needed to perform a soft-reset */
00032   (MMA6800_DEVCTL | (MMA6800_WRITE_REGISTER << CHAR_BIT) | CLEAR),
00033   (MMA6800_DEVCTL | (MMA6800_WRITE_REGISTER << CHAR_BIT) | 0xC0u),
00034   (MMA6800_DEVCTL | (MMA6800_WRITE_REGISTER << CHAR_BIT) | 0x40u),
00035   /* Dummy read after reset */
00036   (MMA6800_DEVCFG | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR),
00037   (MMA6800_DEVCFG | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR) };
00038 
00039 const uint16_t cau16MMA6800ReadAllRegisters[] =
00040 {
00041   (MMA6800_SN0 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN1
00042       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN2
00043       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN3
00044       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_X
00045       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_Y
00046       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_PN
00047       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCTL
00048       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG
00049       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_X
00050       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_Y
00051       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGX
00052       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGY
00053       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XP
00054       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YP
00055       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XN
00056       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YN
00057       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVSTAT
00058       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_COUNT
00059       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_X
00060       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_Y
00061       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR) };
00062 
00063 const uint16_t cau16MMA6500ReadAllRegisters[] =
00064 {
00065   (MMA6800_SN0 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN1
00066       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN2
00067       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN3
00068       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_STDEFL_X
00069       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_STDEFL_Y
00070       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_X
00071       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_Y
00072       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_PN
00073       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCTL
00074       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG
00075       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_X
00076       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_Y
00077       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGX
00078       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGY
00079       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XP
00080       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YP
00081       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XN
00082       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YN
00083       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVSTAT
00084       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_COUNT
00085       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_X
00086       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_Y
00087       | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR) };
00088 
00089 /* Constant table below groups all possible acceleration modes for each */
00090 /* sensor.                                                              */
00091 const uint16_t cau16MMA6800PerformAccelReading[] =
00092 {
00093   /* Config 0 */
00094   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\
00095 
00096       | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE),
00097 
00098   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\
00099 
00100       | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE),
00101   /* Config 1 */
00102   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\
00103 
00104       | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE),
00105 
00106   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\
00107 
00108       | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE),
00109   /* Config 2 */
00110   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\
00111 
00112       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00113 
00114   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\
00115 
00116       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00117   /* Config 3 */
00118   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\
00119 
00120       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE),
00121 
00122   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\
00123 
00124       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE),
00125   /* Config 4 */
00126   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00127       | MMA6800_ARM_DISABLE),
00128 
00129   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00130       | MMA6800_ARM_DISABLE),
00131   /* Config 5 */
00132   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00133       | MMA6800_ARM_ENABLE),
00134 
00135   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00136       | MMA6800_ARM_ENABLE),
00137   /* Config 6 */
00138   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA
00139       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00140 
00141   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA
00142       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00143   /* Config 7 */
00144   (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA
00145       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE),
00146 
00147   (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA
00148       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), };
00149 
00150 const uint16_t cau16MMA6500PerformAccelReading[] =
00151 {
00152   /* Config 0 */
00153   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED
00154       | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE),
00155 
00156   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED
00157       | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE),
00158 
00159   /* Config 1 */
00160   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED
00161       | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE),
00162 
00163   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED
00164       | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE),
00165 
00166   /* Config 2 */
00167   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED
00168       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00169 
00170   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED
00171       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00172 
00173   /* Config 3 */
00174   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED
00175       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE),
00176 
00177   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED
00178       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE),
00179 
00180   /* Config 4 */
00181   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00182       | MMA6800_ARM_DISABLE),
00183 
00184   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00185       | MMA6800_ARM_DISABLE),
00186 
00187   /* Config 5 */
00188   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00189       | MMA6800_ARM_ENABLE),
00190 
00191   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA
00192       | MMA6800_ARM_ENABLE),
00193 
00194   /* Config 6 */
00195   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA
00196       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00197 
00198   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA
00199       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE),
00200 
00201   /* Config 7 */
00202   (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA
00203       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE),
00204 
00205   (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA
00206       | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), };
00207 
00208 /* The element below is a constant array of pointers to functions    */
00209 /* with two elements, namely the address of the scheduled and the    */
00210 /* immediate transfers. This solution allows the user to send either */
00211 /* command just by choosing the index in the array.                  */
00212 uint8_t (* const u8pfnMMA6800BatchOp[])(const uint8_t cu8DSPIInstance,
00213                                         const uint8_t cu8ChipSelect,
00214                                         const uint16_t* pu16DataToSend,
00215                                         uint16_t* pu16UnfilteredDataReceived,
00216                                         uint8_t u8Size) =
00217 
00218 {
00219   &u8fnMMA6800ScheduledBatchOp, &u8fnMMA6800BatchOp };
00220 /*
00221  ******************************************************************************
00222  * Globals
00223  ******************************************************************************
00224  */
00225 /* Global variable array that allows "trash" responses to be scheduled safely*/
00226 uint8_t gau8MMA6800GlobalResult[MMA6800_GLOBAL_BUFFER_SIZE];
00227 /*
00228  ******************************************************************************
00229  * u8fnMMA6800ReadRegister
00230  ******************************************************************************
00231  */
00232 uint8_t u8fnMMA6800ReadRegister(const uint8_t cu8DSPIInstance,
00233                                 const uint8_t cu8ChipSelect,
00234                                 const uint8_t cu8TransferMode,
00235                                 uint16_t u16Register, uint16_t* pu16DataRead)
00236 {
00237   uint16_t u16ReadCmd;
00238   
00239   /* Create data to be sent in the correct format */
00240   u16ReadCmd = (uint16_t)((MMA6800_READ_REGISTER << 8u) | u16Register);
00241   
00242   /* Call the correct fn according to cu8TransferMode */
00243   return ((*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance,
00244                                                   cu8ChipSelect,
00245                                                   (uint16_t*)&u16ReadCmd,
00246                                                   pu16DataRead, 1u));
00247 }
00248 /*
00249  ******************************************************************************
00250  * u8fnMMA6800WriteRegister
00251  ******************************************************************************
00252  */
00253 uint8_t u8fnMMA6800WriteRegister(const uint8_t cu8DSPIInstance,
00254                                  const uint8_t cu8ChipSelect,
00255                                  const uint8_t cu8TransferMode,
00256                                  uint16_t u16Register, uint8_t u8ValueToWrite,
00257                                  uint16_t* pu16DataRead)
00258 {
00259   uint16_t u16WriteCmd;
00260   
00261   u16WriteCmd = (uint16_t)((MMA6800_WRITE_REGISTER << 8u) | u16Register
00262       | u8ValueToWrite);
00263   
00264   /* Call the correct fn according to cu8TransferMode */
00265   return ((*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance,
00266                                                   cu8ChipSelect,
00267                                                   (uint16_t*)&u16WriteCmd,
00268                                                   pu16DataRead, 1u));
00269 }
00270 /*
00271  ******************************************************************************
00272  * u8fnMMA6800Reset
00273  ******************************************************************************
00274  */
00275 uint8_t u8fnMMA6800Reset(const uint8_t cu8DSPIInstance,
00276                          const uint8_t cu8ChipSelect,
00277                          const uint8_t cu8TransferMode)
00278 {
00279   
00280   /* Call the correct fn according to cu8TransferMode */
00281   return ((*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance,
00282                                                   cu8ChipSelect,
00283                                                   (uint16_t*)cau16MMA6800Reset,
00284                                                   (uint16_t*)gau8MMA6800GlobalResult,
00285                                                   (uint8_t)N_ELEMENTS(cau16MMA6800Reset)));
00286 }
00287 /*
00288  ******************************************************************************
00289  * u8fnMMA6800ReadAccel
00290  ******************************************************************************
00291  */
00292 uint8_t u8fnMMA6800ReadAccel(const uint8_t cu8DSPIInstance,
00293                              const uint8_t cu8ChipSelect,
00294                              const uint8_t cu8TransferMode,
00295                              const uint8_t cu8Axis,
00296                              const uint8_t cu8ConfigMemory,
00297                              uint16_t* pu16AccelResults, const uint8_t cu8Accel)
00298 {
00299   /* Declare locals */
00300   uint8_t u8Index;
00301   uint8_t u8Status;
00302   uint8_t u8Counter;
00303   uint8_t u8Offset;
00304   uint16_t* pu16AccelTable;
00305   
00306   /* Init locals */
00307   u8Status = CLEAR;
00308   u8Index = CLEAR;
00309   u8Offset = CLEAR;
00310   u8Counter = (uint8_t)1u;
00311   pu16AccelTable = (uint16_t*)&cau16MMA6800PerformAccelReading;
00312   
00313   /* Figure out where in the table we are */
00314   if(cu8ConfigMemory >= (N_ELEMENTS(cau16MMA6800PerformAccelReading) / 2u))
00315   {
00316     /* This is bad - we are out of the table. flag it as an error and exit */
00317     u8Status = MMA6800_INVALID_MEMORY_LOCATION;
00318   }
00319   else
00320   {
00321     /* Figure out how many readings we need - this will change the offset */
00322     /* within the table */
00323     if(MMA6800_READ_X & cu8Axis)
00324     {
00325       if(MMA6800_READ_Y & cu8Axis)
00326       {
00327         u8Counter++;
00328       }
00329       else
00330       {
00331         /* Nothing */
00332       }
00333     }
00334     else if(MMA6800_READ_Y & cu8Axis)
00335     {
00336       u8Offset++;
00337     }
00338     else
00339     {
00340       /* Nothing */
00341     }
00342 
00343     /* Here, we'll calculate the index for the table based on the above */
00344     /* operations.                                                      */
00345     u8Index = (uint8_t)((uint8_t)2u * cu8ConfigMemory) + u8Offset;
00346     
00347     /* Depending on what type of accelerometer is the type of request   */
00348     /* that we will be performing.                                      */
00349     if(MESQUITE == cu8Accel)
00350     {
00351       pu16AccelTable = (uint16_t*)&cau16MMA6800PerformAccelReading[u8Index];
00352     }
00353     else if(SYCAMORE == cu8Accel)
00354     {
00355       pu16AccelTable = (uint16_t*)&cau16MMA6500PerformAccelReading[u8Index];
00356       
00357     }
00358     else
00359     {
00360       /* Accelerometer is not defined */
00361       u8Status = MMA6800_ERROR_ACCEL;
00362     }
00363 
00364     /* Perform the transfer, either automatically or scheduled */
00365     u8Status
00366         = (*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance,
00367                                                   cu8ChipSelect,
00368                                                   (const uint16_t*)pu16AccelTable,
00369                                                   pu16AccelResults, u8Counter);
00370     
00371     if(MMA6800_TRANSFER_MODE_IS_IMMEDIATE == cu8TransferMode)
00372     {
00373       u8Status |= u8fnMMA6800ExtractAccelResponse(pu16AccelResults,
00374                                                   pu16AccelResults, u8Counter,
00375                                                   cu8Accel);
00376     }
00377     else
00378     {
00379       /* We are done */
00380     }
00381   }
00382   
00383   return (u8Status);
00384 }
00385 /*
00386  ******************************************************************************
00387  * u8fnMMA6800ExtractRegisterResponse
00388  ******************************************************************************
00389  */
00390 uint8_t u8fnMMA6800ExtractRegisterResponse(const uint16_t* pu16RawResponse,
00391                                            uint8_t* pu8Response, 
00392                                            uint8_t u8Size)
00393 {
00394   /* Declare local variables */
00395   uint8_t u8Status;
00396   uint8_t u8Counter;
00397   
00398   /* Init local variables */
00399   u8Status = CLEAR;
00400   u8Counter = CLEAR;
00401   
00402   for(; u8Counter < u8Size; u8Counter++)
00403   {
00404     /* Check Parity */
00405     if(CLEAR == u16fnCheckOddParity(*pu16RawResponse, CLEAR))
00406     {
00407       /* Is this a register operation? */
00408       u8Status |= u8fnMMA6800ResponseAnalysis(*pu16RawResponse);
00409       if(MMA6800_REGISTER_RESPONSE == u8Status)
00410       {
00411         u8Status = CLEAR;
00412         *pu8Response = (uint8_t)*pu16RawResponse;
00413       }
00414       else
00415       {
00416         *pu8Response = CLEAR;
00417       }
00418 
00419     }
00420     else
00421     {
00422       /* If invalid parity is found, clear this particular response, */
00423       /* and make sure to flag it in the status byte.                */
00424       u8Status |= MMA6800_INVALID_PARITY;
00425       *pu8Response = CLEAR;
00426     }
00427 
00428     pu16RawResponse++;
00429     pu8Response++;
00430   }
00431   return (u8Status);
00432 }
00433 /*
00434  ******************************************************************************
00435  * u8fnMMA6800ExtractAccelResponse
00436  ******************************************************************************
00437  */
00438 uint8_t u8fnMMA6800ExtractAccelResponse(const uint16_t* pu16RawResponse,
00439                                         uint16_t* pu16Response, 
00440                                         uint8_t u8Size,
00441                                         const uint8_t cu8Accel)
00442 {
00443   /* Declare local variables */
00444   uint8_t u8Status;
00445   uint8_t u8Counter;
00446   
00447   /* Init local variables */
00448   u8Status = CLEAR;
00449   u8Counter = CLEAR;
00450   
00451   for(; u8Counter < u8Size; u8Counter++)
00452   {
00453     /* Check Parity */
00454     if(CLEAR == u16fnCheckOddParity(*pu16RawResponse, CLEAR))
00455     {
00456       /* Is this a register operation? */
00457       u8Status = u8fnMMA6800ResponseAnalysis(*pu16RawResponse);
00458       if(MMA6800_ACCEL_READING == u8Status)
00459       {
00460         u8Status = CLEAR;
00461         if (MESQUITE == cu8Accel)
00462         {
00463           *pu16Response = *pu16RawResponse & MMA6800_RAW_ACCEL_MASK;
00464         }
00465         else if (SYCAMORE == cu8Accel)
00466         {
00467           *pu16Response = *pu16RawResponse & MMA6500_RAW_ACCEL_MASK;
00468           /* Format the 12-bits word with D0 in LSB and D11 in BIT12 location*/
00469           *pu16Response = (((0xC000u & *pu16Response) >> 14) | (*pu16Response << 2));
00470         }
00471         else
00472         {
00473           /* Accelerometer is not defined */
00474           u8Status = MMA6800_ERROR_ACCEL;
00475         }
00476       }
00477       else
00478       {
00479         *pu16Response = 0xFC00;
00480       }
00481 
00482     }
00483     else
00484     {
00485       /* If invalid parity is found, clear this particular response, */
00486       /* and make sure to flag it in the status byte.                */
00487       u8Status |= MMA6800_INVALID_PARITY;
00488       *pu16Response = 0xFC00;
00489     }
00490 
00491     pu16RawResponse++;
00492     pu16Response++;
00493   }
00494   return (u8Status);
00495 }
00496 /*
00497  ******************************************************************************
00498  * u8fnMMA6800ResponseAnalysis
00499  ******************************************************************************
00500  */
00501 static uint8_t u8fnMMA6800ResponseAnalysis(uint16_t u16RawResponse)
00502 {
00503   /* Declare local variables */
00504   uint8_t u8Status;
00505   
00506   /* Init local variables */
00507   u8Status = CLEAR;
00508   
00509   if(MMA6800_REGISTER_RESP_SIGNATURE == ((BIT11 | BIT10) & u16RawResponse))
00510   {
00511     /* This datagram is either a message or an error */
00512     u8Status = u8fnMMA6800ErrorResponseAnalysis(u16RawResponse);
00513     
00514     if(CLEAR == u8Status)
00515     {
00516       u8Status = MMA6800_REGISTER_RESPONSE;
00517     }
00518     else
00519     {
00520       /* Report the status byte provided by the called routine */
00521     }
00522   }
00523   else
00524   {
00525     /* This message is likely an accel reading */
00526     u8Status = MMA6800_ACCEL_READING;
00527   }
00528   
00529   return (u8Status);
00530   
00531 }
00532 /*
00533  ******************************************************************************
00534  * u8fnMMA6800ErrorResponseAnalysis
00535  ******************************************************************************
00536  */
00537 static uint8_t u8fnMMA6800ErrorResponseAnalysis(const uint16_t cu16ReceivedWord)
00538 {
00539   uint8_t u8Status;
00540   
00541   u8Status = CLEAR;
00542   
00543   /* Once data has been received, check its integrity, starting with     */
00544   /* parity */
00545   if(CLEAR == u16fnCheckOddParity(cu16ReceivedWord, CLEAR))
00546   {
00547     /* Identify if error or register operation */
00548     if((CLEAR == (BIT14 & cu16ReceivedWord)) || (CLEAR == ((BIT13 | BIT9)
00549         & cu16ReceivedWord)))
00550     {
00551       /* Error must be reported */
00552       u8Status = MMA6800_ERROR_DATAGRAM;
00553     }
00554     else
00555     {
00556       /* We're good! */
00557     }
00558   }
00559   else
00560   {
00561     u8Status = MMA6800_INVALID_PARITY;
00562   }
00563   
00564   return (u8Status);
00565 }
00566 /*
00567  ******************************************************************************
00568  * u16fnMMA6800AddParityToCommand
00569  ******************************************************************************
00570  */
00571 static uint16_t u16fnMMA6800AddParityToCommand(uint16_t u16RawCommand)
00572 {
00573   uint16_t u16Command;
00574   
00575   u16Command = CLEAR;
00576   
00577   if(u16RawCommand & BIT13)
00578   {
00579     /* This is an acceleration request - parity bit is set at the end of   */
00580     /* datagram. Refer to spec for more info.                              */
00581     u16Command = u16fnCheckOddParity(u16RawCommand, BIT0);
00582   }
00583   else
00584   {
00585     /* This is a register operation. Parity bit is set in MSB. Refer to    */
00586     /* spec for more info.                                                 */
00587     u16Command = u16fnCheckOddParity(u16RawCommand, BIT15);
00588   }
00589   
00590   return (u16Command);
00591 }
00592 /*
00593  ******************************************************************************
00594  * u8fnMMA6800ScheduledBatchOp
00595  ******************************************************************************
00596  */
00597 uint8_t u8fnMMA6800ScheduledBatchOp(const uint8_t cu8DSPIInstance,
00598                                     const uint8_t cu8ChipSelect,
00599                                     const uint16_t* pu16DataToSend,
00600                                     uint16_t* pu16UnfilteredDataReceived,
00601                                     uint8_t u8Size)
00602 {
00603   uint8_t u8Status;
00604   uint16_t u16Counter;
00605   uint16_t au16CurrentWordsToSend[MMA6800_MSG_BUFFER_SIZE];
00606   
00607   /* Init locals */
00608   u8Status = CLEAR;
00609   u16Counter = CLEAR;
00610   
00611   /* Next, we shall send the rest of the datagram and store the read-back    */
00612   for(u16Counter = CLEAR; u16Counter < u8Size; u16Counter++)
00613   {
00614     /* Check parity. */
00615     au16CurrentWordsToSend[u16Counter] =
00616       u16fnMMA6800AddParityToCommand(*(pu16DataToSend++));
00617   }
00618   /* Write a dummy to recoup the last response */
00619   au16CurrentWordsToSend[u16Counter]
00620       = u16fnMMA6800AddParityToCommand(MMA6800_SN0);
00621   
00622   /* We must wait for the previous transmission to end before launching  */
00623   /* a new one. We must also make sure we don't stay here forever.       */
00624 
00625   /* If we came out of the above wait without expiring the timer, we     */
00626   /* should continue. otherwise, flag as an error.                       */
00627   u8Status = u8fnSchedDSPIMailTransfer(cu8DSPIInstance, cu8ChipSelect, CLEAR,
00628                                        CLEAR,
00629                                        (uint16_t*)au16CurrentWordsToSend,
00630                                        pu16UnfilteredDataReceived,
00631                                        (uint16_t)(u8Size + 1u));
00632   
00633   return (u8Status);
00634 }
00635 /*
00636  ******************************************************************************
00637  * u8fnMMA6800BatchOp
00638  ******************************************************************************
00639  */
00640 uint8_t u8fnMMA6800BatchOp(const uint8_t cu8DSPIInstance,
00641                            const uint8_t cu8ChipSelect,
00642                            const uint16_t* pu16DataToSend,
00643                            uint16_t* pu16UnfilteredDataReceived, uint8_t u8Size)
00644 {
00645   uint8_t u8Status;
00646   uint16_t u16Counter;
00647   uint16_t u16TimeOut;
00648   uint16_t u16CurrentWordToSend;
00649   uint16_t u16FirstWordReceived;
00650   
00651   /* Init locals */
00652   u8Status = CLEAR;
00653   u16Counter = CLEAR;
00654   u16TimeOut = CLEAR;
00655   u16CurrentWordToSend = CLEAR;
00656   u16FirstWordReceived = CLEAR;
00657   
00658   /* Use DSPI to send config - we need to send one more word since the result*/
00659   /* will be sent with the second one. The content of the last word is       */
00660   /* irrelevant.                                                             */
00661 
00662   /* First, send the first word and simply ignore whatever is received */
00663   /* Check parity. */
00664   u16CurrentWordToSend = u16fnMMA6800AddParityToCommand(*(pu16DataToSend++));
00665   u8Status = u8fnDSPITranscieve(cu8DSPIInstance, cu8ChipSelect,
00666                                 (uint16_t*)&u16CurrentWordToSend,
00667                                 (uint16_t*)&u16FirstWordReceived, 1u);
00668   
00669   /* Next, we shall send the rest of the datagram and store the read-back    */
00670   for(u16Counter = 1u; u16Counter < u8Size; u16Counter++)
00671   {
00672     /* Only proceed if we are clear to go */
00673     if(CLEAR == u8Status)
00674     {
00675       /* Check parity. */
00676       u16CurrentWordToSend = u16fnMMA6800AddParityToCommand(*(pu16DataToSend++));
00677 
00678       /* We must wait for the previous transmission to end before launching  */
00679       /* a new one. We must also make sure we don't stay here forever.       */
00680       u16TimeOut = CLEAR;
00681       while((u8fnIsDSPIBusy(cu8DSPIInstance >> 4u)) &&
00682           (USHRT_MAX > u16TimeOut))
00683       {
00684         u16TimeOut++;
00685       }
00686 
00687       /* If we came out of the above wait without expiring the timer, we     */
00688       /* should continue. otherwise, flag as an error.                       */
00689       if((USHRT_MAX) > u16TimeOut)
00690       {
00691         u8Status = u8fnDSPITranscieve(cu8DSPIInstance, cu8ChipSelect,
00692             (uint16_t*)&u16CurrentWordToSend,
00693             pu16UnfilteredDataReceived++, 1u);
00694       }
00695       else
00696       {
00697         /* There's something wrong */
00698         u8Status = MMA6800_TIMED_OUT;
00699       }
00700     }
00701     else
00702     {
00703       /* Loop til we exit */
00704     }
00705   }
00706 
00707   /* Only go on if we still can */
00708   if(CLEAR == u8Status)
00709   {
00710     /* Dummy write just to get the last response */
00711     /* Check parity. */
00712     u16CurrentWordToSend = u16fnMMA6800AddParityToCommand(MMA6800_SN0);
00713     
00714     /* If we came out of the above wait without expiring the timer, we       */
00715     /* should continue. otherwise, flag as an error.                         */
00716     u16TimeOut = CLEAR;
00717     while((u8fnIsDSPIBusy(cu8DSPIInstance >> 4u)) && (USHRT_MAX > u16TimeOut))
00718     {
00719       u16TimeOut++;
00720     }
00721     /* If we came out of the above wait without expiring the timer, we       */
00722     /* should continue. otherwise, flag as an error.                         */
00723     if((USHRT_MAX) > u16TimeOut)
00724     {
00725       u8Status = u8fnDSPITranscieve(cu8DSPIInstance, cu8ChipSelect,
00726                                     (uint16_t*)&u16CurrentWordToSend,
00727                                     pu16UnfilteredDataReceived, 1u);
00728     }
00729     else
00730     {
00731       /* There's something wrong */
00732       u8Status = MMA6800_TIMED_OUT;
00733     }
00734   }
00735   else
00736   {
00737     /* Just get out of here please */
00738   }
00739   
00740   return (u8Status);
00741 }
00742 /*
00743  ******************************************************************************
00744  *
00745  *  End of file.
00746  *
00747  ******************************************************************************
00748  */